package com.itcast.infohide.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.itcast.infohide.config.MinioConfig;
import com.itcast.infohide.entity.OperateLogPO;
import com.itcast.infohide.entity.FileVO;
import com.itcast.infohide.entity.User;
import com.itcast.infohide.mapper.OperateLogMapper;
import com.itcast.infohide.mapper.UserMapper;
import com.itcast.infohide.service.UserService;
import com.itcast.infohide.util.JwtUtil;
import io.minio.DownloadObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    // 注入minio配置文件
    @Resource
    private MinioConfig minioConfig;

    // 注入minio client
    @Resource
    private MinioClient client;

    @Resource
    private OperateLogMapper operateLogMapper;


    @Override
    public ResponseEntity saveUser(User user) {
        String imageKey = "4";
        String infoKey = "5";
        user.setImageKey(imageKey);
        user.setDataKey(infoKey);

        if (ObjectUtils.isNotEmpty(userMapper.selectByAccount(user.getAccount()))
        || ObjectUtils.isNotEmpty(userMapper.selectByName(user.getName()))) {
            throw new RuntimeException("该账号已注册");
        }

        // 获取当前时间的时间戳，单位为秒
        Instant timestamp = Instant.now();
        LocalDateTime dateTime = LocalDateTime.ofInstant(timestamp, ZoneId.systemDefault());
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = dateTime.format(formatter);
        user.setCreateTime(formattedDateTime);
        user.setUpdateTime(formattedDateTime);
        userMapper.insertOne(user);
        return ResponseEntity.ok(user);
    }

    @Override
    public User findById(String id) {
//        QueryWrapper<User> qw = new QueryWrapper<>();
//        qw.eq("account",id);
        User user = userMapper.selectByAccount(id);
        return user;
    }

    @Override
    public User findById(long uid) {
        User user = userMapper.selectById(uid);
        return user;
    }

    //根据token获取用户id
    @Override
    public long fromToken(String token) {
        //jwt反编译token拿到用户的id
        Map map = JwtUtil.parseToken(token, "tanhua");
        long uid = Long.parseLong(map.get("id").toString());
        return uid;
    }

    //注册、登录
    @Override
    public ResponseEntity loginVerification(User userPO) {
        // 在查询用户
        User user = findById(userPO.getAccount());

//        //定义标识(默认老用户)
//        Boolean flg=false;

        if(ObjectUtil.isEmpty(user)){
            throw new RuntimeException("该账号未注册！");
            //新用户--注册
//            user=new User();
//            BeanUtil.copyProperties(userPO, user);
//            ResponseEntity id = saveUser(user); //保存新用户 且返回新用户在数据库的id
//            User body = (User) id.getBody();
//            user.setId(body.getId()); //100
        }

        //对比密码
        if (!userPO.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码输入有误，请重新输入！");
        }

        Map mp = new HashMap();
        mp.put("userId",user.getId());
        mp.put("name", user.getName());

        return ResponseEntity.ok(mp);
    }

    @Override
    public String log(OperateLogPO operateLogPO) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String id = UUID.randomUUID().toString();
        operateLogPO.setId(id);
        operateLogPO.setCreateTime(format.format(new Date(System.currentTimeMillis())));
        if (0 == operateLogPO.getIsEmbed()) {
            if (StringUtils.isNotBlank(operateLogPO.getImageKey())) {
                operateLogPO.setIsPlaintext(1);
            }else {
                operateLogPO.setIsPlaintext(0);
            }
        }
        if (1 == operateLogPO.getIsEmbed()) {
            if (StringUtils.isBlank(operateLogPO.getImageKey())
                    && StringUtils.isBlank(operateLogPO.getDataKey())) {
                operateLogPO.setIsPlaintext(0);
            }
            //处理密文
            if (StringUtils.isNotBlank(operateLogPO.getImageKey())
                    || StringUtils.isNotBlank(operateLogPO.getDataKey())) {
                //设置密文标识
                operateLogPO.setIsPlaintext(1);
                //密文提取
                if (operateLogPO.getCiphertextType() == 0) {

                }
                //密文图像恢复
                if (operateLogPO.getCiphertextType() == 1) {
                }
                //密文提取并恢复
                if (operateLogPO.getCiphertextType() == 2) {

                }
            }
        }

        operateLogMapper.insertOne(operateLogPO);


        return "ok";
    }

    @Override
    public FileVO upload(MultipartFile file) {
        FileVO fileVO = new FileVO();
        try {
            // 获取文件真实名称
            String originalFilename = file.getOriginalFilename();
            // 获取文件的扩展名 例如.jpg .doc
            String extname = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 构建文件上传相关信息
            PutObjectArgs args = PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(originalFilename)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            // 将文件上传到minio服务器
            client.putObject(args);
            log.info("文件上传成功");
            // 组装文件信息，返回前端 或者存入数据路
            String url = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + originalFilename;
            fileVO.setUrl(url);
            fileVO.setSize(file.getSize());
            fileVO.setFileName(originalFilename);
            fileVO.setExtname(extname);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileVO;
    }


    @Override
    public List<OperateLogPO> select(Integer isEmbed) {
        return operateLogMapper.selectByFlag(isEmbed);
    }

    @Override
    public String compare(String imageUrl1, String imageUrl2) {
        try {
            // 下载第一张图片并读取为 BufferedImage
            BufferedImage image1 = downloadObject(client, imageUrl1);
            // 下载第二张图片并读取为 BufferedImage
            BufferedImage image2 = downloadObject(client, imageUrl2);
            // 转换为灰度图
            BufferedImage grayImg1 = convertToGrayscale(image1);
            BufferedImage grayImg2 = convertToGrayscale(image2);

            // 比较尺寸
            if (grayImg1.getWidth() != grayImg2.getWidth() || grayImg1.getHeight() != grayImg2.getHeight()) {
                return "两张图片不一致";
            }

            int width = 512;
            int height = 512;

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int pixel1 = image1.getRGB(x, y);
                    int pixel2 = image2.getRGB(x, y);

                    if (pixel1!= pixel2) {
                        return "两张图片不一致";
                    }
                }
            }

            return "两张图片一致";
        } catch (IOException | MinioException | NoSuchAlgorithmException | InvalidKeyException e) {
            e.printStackTrace();
            return "两张图片不一致";
        }
    }

    public static BufferedImage downloadObject(MinioClient minioClient, String imageUrl) throws IOException, MinioException, NoSuchAlgorithmException, InvalidKeyException {
        String tempFilePath = "temp_image.jpg";
        DownloadObjectArgs args = DownloadObjectArgs.builder()
                .bucket("info") // 设置桶名
                .object(imageUrl)
                .filename(tempFilePath)
                .build();
        minioClient.downloadObject(args);
        return ImageIO.read(new File(tempFilePath));
    }

    private static BufferedImage convertToGrayscale(BufferedImage original) {
        BufferedImage grayscale = new BufferedImage(
                original.getWidth(), original.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
        for (int i = 0; i < original.getWidth(); i++) {
            for (int j = 0; j < original.getHeight(); j++) {
                int red = new Color(original.getRGB(i, j)).getRed();
                int green = new Color(original.getRGB(i, j)).getGreen();
                int blue = new Color(original.getRGB(i, j)).getBlue();
                int luminance = (int) (red * 0.21 + green * 0.72 + blue * 0.07);
                int newPixel = new Color(luminance, luminance, luminance).getRGB();
                grayscale.setRGB(i, j, newPixel);
            }
        }
        return grayscale;
    }
}
